﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace QbservableCore.Serialization
{
    /// <summary>
    /// 
    /// </summary>
    [DataContract]
    public class TypeRepresentation
    {
        #region Ctor

        public TypeRepresentation(Type type)
        {
            InnerType = type;
        }

        #endregion // Ctor

        #region TypeName

        private string _typeName;
        /// <summary>
        /// Gets or sets the name of the type.
        /// </summary>
        /// <value>
        /// The name of the type.
        /// </value>
        [DataMember]
        private string TypeName
        {
            get { return _typeName; }
            set { _typeName = value; }
        }

        #endregion // TypeName

        #region AssemblyName

        private string _assemblyName;
        /// <summary>
        /// Gets or sets the name of the assembly.
        /// </summary>
        /// <value>
        /// The name of the assembly.
        /// </value>
        [DataMember]
        private string AssemblyName
        {
            get { return _assemblyName; }
            set { _assemblyName = value; }
        }

        #endregion // AssemblyName

        public Type InnerType { get; private set; }

        #region Hook on serialization and deserialization

        #region OnSerializing

        /// <summary>
        /// Called when [serializing].
        /// </summary>
        /// <param name="context">The context.</param>
        [OnSerializing]
        public void OnSerializing(StreamingContext context)
        {
            var convention = context.Context as IQbservableConvention;
            convention.JsonSettings.Binder.BindToName(InnerType, out _assemblyName, out _typeName);
        }

        #endregion // OnSerializing

        #region OnDeserialized

        /// <summary>
        /// Called when [deserialized].
        /// </summary>
        /// <param name="context">The context.</param>
        [OnDeserialized]
        public void OnDeserialized(StreamingContext context)
        {
            var convention = context.Context as IQbservableConvention;
            InnerType = convention.JsonSettings.Binder.BindToType(_assemblyName, _typeName);
        }

        #endregion // OnDeserialized

        #endregion // Hook on serialization and deserialization

        #region Casting overloads

        /// <summary>
        /// TypeRepresentation to Type overloading [Type t = new TypeRepresentation(...)].
        /// </summary>
        /// <param name="t">The t.</param>
        /// <returns></returns>
        public static explicit operator Type(TypeRepresentation t)
        {
            return t.InnerType;
        }

        /// <summary>
        /// Types to TypeRepresentation overloading [TypeRepresentation t = (TypeRepresentation)typeof(int)].
        /// </summary>
        /// <param name="t">The t.</param>
        /// <returns></returns>
        public static explicit operator TypeRepresentation(Type t)
        {
            return new TypeRepresentation(t);
        }

        #endregion // Casting overloads
    }
}
